import React, { PureComponent, createRef } from 'react'
import { Card, Form, Input, Cascader, Button, message } from 'antd'
import { ArrowLeftOutlined } from "@ant-design/icons"
import LinkButton from '@/components/link-button'
import memoryUtils from "@/utils/memoryUtils"
import { reqCategorys, reqAddOrUpdateProduct } from '@/api'
import PicturesWall from './pictures-wall'
import RichTextEditor from './rich-text-editor'

const { Item } = Form
const { TextArea } = Input

// product的添加和更新子路由的组件

export default class ProductAddUpdate extends PureComponent {
  constructor(props) {
    super(props);
    this.formRef = createRef();
    //创建用来保存ref标签的对象的容器
    this.pw = createRef();
    this.editor = createRef();
    this.state = {
      options: []
    }
    //取出携带的state
    const product = memoryUtils.product  //如果是添加就没有值
    //保存一个是否为更新的标识
    this.isUpdate = !!product._id
    //保存商品,如果没有保存的是{} 
    this.product = product || {}
  }

  /**
   *  异步获取一级和二级分类列表，并显示
   *  async函数的返回值是一个promise对象，而promise的结果和值是由async的结果来决定的
   */
  getCategorys = async (parentId) => {
    let result = await reqCategorys(parentId)
    if (result.data.status === 0) {
      const categorys = result.data.data
      //如果是一级分类
      if (parentId === '0') {
        this.initOptions(categorys);
      } else {
        //二级列表
        return categorys  //返回二级列表===>当前async函数返回的promise就会成功且value为categorys
      }
    }
  }


  initOptions = async (categorys) => {
    //根据categorys生成options数组
    const options = categorys.map(c => ({
      value: c._id,
      label: c.name,
      isLeaf: false,
    }))
    //如果是一个二级分类的商品的更新
    const { isUpdate, product } = this
    const { pCategoryId } = product
    if (isUpdate && pCategoryId !== '0') {
      //获取对应的二级分类的列表
      const subCategorys = await this.getCategorys(pCategoryId);
      //生成二级列表的options
      const childOptions = subCategorys.map((c) => ({
        value: c._id,
        label: c.name,
        isLeaf: true,
      }))
      //找到对应的商品的一级的options对象
      const targetOption = options.find(option => option.value === pCategoryId)
      //关联到一级分类options上去 
      targetOption.children = childOptions;
    }
    //更新options状态
    this.setState({ options: [...options] })
  }
  // 用于加载下一级列表的回调函数
  loadData = async (selectedOptions) => {
    //得到选择的option对象
    const targetOption = selectedOptions[selectedOptions.length - 1];
    //根据选中的分类请求获取二级分类列表
    const subCategorys = await this.getCategorys(targetOption.value)
    if (subCategorys && subCategorys.length > 0) {
      //生成一个二级分类的列表
      const childOptions = subCategorys.map(c => ({
        value: c._id,
        label: c.name,
        isLeaf: true,
      }))

      //关联到当前option上
      targetOption.children = childOptions

    } else {
      //当前选中的分类没有二级分类
      //动态设置选中项的没有children
      targetOption.isLeaf = true
    }
    //更新options状态   
    this.setState({
      options: [...this.state.options]
    })

  };
  //验证价格的自定义函数
  validatePrice = (rule, value) => {
    if (value * 1 > 0) {
      return Promise.resolve();  //验证通过
    } else {
      return Promise.reject("价格必须大于0")
    }
  }
  //表单的提交方法
  submit = () => {
    const formInstance = this.formRef.current

    formInstance.validateFields().then(async (values) => {
      if (values) {
        const { name, desc, price, categoryIds } = values
        //1.收集数据并封装成product对象 
        let categoryId, pCategoryId;
        if (categoryIds.length === 1) {
          pCategoryId = '0';
          categoryId = categoryIds[0]
        } else {
          pCategoryId = categoryIds[0];
          categoryId = categoryIds[1];
        }
        const imgs = this.pw.current.getImgs();
        const detail = this.editor.current.getDetail();
        //2.调用接口请求函数去添加和更新
        const product = { name, desc, price, imgs, detail, pCategoryId, categoryId };
        //如果是更新则需要添加_id
        if (this.isUpdate) {
          product._id = this.product._id;
        }

        let result = await reqAddOrUpdateProduct(product);
        //3.根据结果提示
        if (result.data.status === 0) {
          message.success(`${this.isUpdate ? '更新' : '添加'}商品成功！`);
          this.props.history.goBack();
        } else {
          message.error(`${this.isUpdate ? '更新' : '添加'}商品失败！`);
        }
      }
    })

  }

  componentDidMount() {
    this.getCategorys('0')
  }

  //在卸载清除之前保存的数据
  componentWillUnmount(){
    memoryUtils.product={}
  }

  render() {
    const { isUpdate, product } = this
    const { categoryId, pCategoryId, imgs, detail } = product
    const categories = [] //用来接收级联的分类id的数组 
    if (isUpdate) {
      //商品是一个一级分类的商品
      if (pCategoryId === '0') {
        categories.push(categoryId)
      } else {
        //商品是一个二级分类的商品
        categories.push(pCategoryId)
        categories.push(categoryId)
      }
    }

    const title = (
      <span>
        <LinkButton onClick={() => this.props.history.goBack()}>
          <ArrowLeftOutlined style={{ fontSize: 20 }} />
        </LinkButton>
        <span>{isUpdate ? '修改商品' : '添加商品'}</span>
      </span>
    )
    return (
      <Card title={title}>
        {/* labelCol指定label的宽度  wrapperCol指定右侧表单包裹的宽度*/}
        <Form labelCol={{ span: 4 }} wrapperCol={{ span: 8 }} ref={this.formRef}>
          <Item label="商品名称" name="name" rules={[{ required: true, message: '请输入商品的名称!' }]} initialValue={product.name}>
            <Input placeholder='请输入商品名称' />
          </Item>

          <Item label="商品描述" name="desc" rules={[{ required: true, message: '请输入商品的描述!' }]} initialValue={product.desc}>
            <TextArea placeholder="请输入商品描述" allowClear autoSize={{ minRows: 2, maxRows: 6 }} />
          </Item>

          <Item label="商品价格" name="price" rules={[{ required: true, message: '请输入商品的价格!' }, { validator: this.validatePrice }]} initialValue={product.price}>
            <Input type='number' placeholder='请输入商品的价格' addonAfter="元" />
          </Item>

          <Item label="商品分类" name="categoryIds" rules={[{ required: true, message: '请选择商品分类!' }]} initialValue={categories}>
            <Cascader
              options={this.state.options} //需要显示的列表数据数组
              loadData={this.loadData}  //当选择某个列表项加载下一级列表的监听回调
              placeholder="请选择商品分类"
              changeOnSelect
            />
          </Item>

          <Item label="商品图片">
            <PicturesWall ref={this.pw} imgs={imgs} />
          </Item>
          <Item label="商品详情" labelCol={{ span: 4 }} wrapperCol={{ span: 20 }} >
            <RichTextEditor ref={this.editor} detail={detail} />
          </Item>
          <Item>
            <Button type='primary' onClick={this.submit}>提交</Button>
          </Item>
        </Form>
      </Card>
    )
  }
}
